package controllers

import (
	"encoding/base64"
	"errmsg"
	"errors"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/validation"
	"smart_home/api/models"
	"smart_home/api/utils/sms"
	"smart_home/api/utils/token"
	"time"
	"tools"
)

type DefaultController struct {
	BaseController
}

type regPost struct {
	Mobile   int64  `form:"mobile" json:"mobile"`
	Password string `form:"password" json:"password"`
	Vcode    string `form:"vcode" json:"vcode"`
}

type loginPost struct {
	Mobile         int64  `form:"mobile" json:"mobile"`
	Password       string `form:"password" json:"password"`
	RegistrationId string `form:"registration_id" json:"registration_id"`
	DeviceId       string `form:"device_id" json:"device_id"`
	Token          string `json:"token"`
}

// @Title register
// @Description 用户注册
// @router /register [post]
func (c *DefaultController) Register() {
	var (
		reg        *regPost
		err        error
		vali       validation.Validation
		passDecode []byte
		pwd        []byte
	)

	reg = &regPost{}
	err = c.ParseData(reg)
	if err != nil {
		logs.Info("register user parse data error:", err)
		c.Error(errmsg.ErrResponseParameter)
	}

	// 数据验证
	vali = validation.Validation{}
	vali.Required(reg.Mobile, "mobile").Message("请输入手机号")
	vali.Mobile(reg.Mobile, "mobile").Message("手机号不正确, 由长度为11位的数字组成")
	vali.Required(reg.Password, "password").Message("请输入用户密码")
	vali.Required(reg.Vcode, "vcode").Message("请输入手机验证码")
	if vali.HasErrors() {
		logs.Info("register user validate data error:", vali.Errors[0])
		c.Error(vali.Errors[0])
		return
	}

	// base64解码
	passDecode, err = base64.StdEncoding.DecodeString(reg.Password)
	if err != nil {
		logs.Error("register user base64 decode error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	// rsa解密
	pwd, err = tools.Decrypt(passDecode)
	if err != nil {
		logs.Error("register user password decode error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	// 验证密码
	reg.Password = string(pwd)
	vali.MaxSize(reg.Password, 18, "password").Message("密码由6到18位字符组成")
	vali.MinSize(reg.Password, 6, "password").Message("密码由6到18位字符组成")
	if vali.HasErrors() {
		logs.Info("register user validate data error:", vali.Errors[0])
		c.Error(vali.Errors[0])
		return
	}

	// 验证短信验证码
	if err = sms.ValidateCode(reg.Mobile, reg.Vcode); err != nil {
		logs.Info("register user validate sms date error:", err)
		c.Error(err)
		return
	}

	// 判断用户是否已存在
	if models.IsExistsUser(reg.Mobile) {
		err := errors.New("用户已存在")
		logs.Info("user register error:", err)
		c.Error(err)
		return
	}

	if err = models.AddUser(reg.Mobile, reg.Password); err != nil {
		logs.Error("register user error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	c.Success(nil)
}

// @Title Login
// @Description 用户登录系统
// @router /login [post]
func (c *DefaultController) Login() {
	var (
		lg         *loginPost
		err        error
		valid      validation.Validation
		passDecode []byte
		pwd        []byte
		user       *models.User
		tk         string
	)

	lg = &loginPost{}
	err = c.ParseData(lg)
	if err != nil {
		logs.Info("login error:", err)
		c.Error(errmsg.ErrResponseParameter)
	}

	valid = validation.Validation{}
	valid.Required(lg.Mobile, "mobile").Message("请输入手机号码")
	valid.Mobile(lg.Mobile, "mobile").Message("手机号码不正确, 由长度为11位的数字组成")
	valid.Required(lg.Password, "password").Message("请输入密码")
	valid.Required(lg.RegistrationId, "registration_id").Message("极光id不能为空")
	valid.Required(lg.DeviceId, "device_id").Message("设备id不能为空")
	if valid.HasErrors() {
		logs.Info("login error:", valid.Errors[0])
		c.Error(valid.Errors[0])
		return
	}

	// base64解码
	passDecode, err = base64.StdEncoding.DecodeString(lg.Password)
	if err != nil {
		logs.Error("login error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	// rsa解密
	pwd, err = tools.Decrypt(passDecode)
	if err != nil {
		logs.Error("login error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	lg.Password = string(pwd)
	valid.MaxSize(lg.Password, 18, "password").Message("密码由6到18位字符组成")
	valid.MinSize(lg.Password, 6, "password").Message("密码由6到18位字符组成")
	if valid.HasErrors() {
		logs.Error("login error:", err)
		c.Error(valid.Errors[0])
		return
	}

	if user, err = models.Login(lg.Mobile, lg.Password); err != nil {
		logs.Info("login error:", err)
		c.Error(err)
		return
	}

	// 已经有用户再登陆该账号
	if otk := token.IsLogin(user.Id); len(otk) > 0 {
		ou := token.Get(otk)
		if ou != nil && ou.DevId != lg.DeviceId {
			err = tools.NewJpush().
				SetID(ou.RegId).
				SetAlert("检测到您的账号在另一台设备登录").
				Jump("login").
				SetMessage("token", otk).
				Send()
			if err != nil {
				logs.Error(err)
				c.Error(errmsg.ErrResponseSystem)
				return
			}
			if err = models.AddMessage(ou.Uid, "异地登陆", "检测到您的账号在另一台设备登录"); err != nil {
				logs.Error(err)
				c.Error(errmsg.ErrResponseSystem)
				return
			}
		}

		if err = token.Del(user.Id, otk); err != nil {
			c.Error(errors.New("登陆失败"))
			return
		}
	}

	if tk, err = token.Put(user.Id, lg.RegistrationId, lg.DeviceId); err != nil {
		c.Error(errors.New("登陆失败"))
		return
	}

	c.Success(&map[string]interface{}{
		"appsecret": tk,
		"expire_in": 24 * 30 * time.Hour / 1000,
		"user":      user,
	})
}

// @Title ResetPassword
// @Description 忘记密码 / 重置密码
// @Param	mobile		query 	string	true		"The mobile for reset"
// @Param	password		query 	string	true		"The password for login"
// @router /reset [post]
func (c *DefaultController) ResetPassword() {
	var (
		reg        *regPost
		err        error
		vali       validation.Validation
		passDecode []byte
		pwd        []byte
	)

	reg = &regPost{}
	err = c.ParseData(reg)
	if err != nil {
		logs.Info("reset password parser data error:", err)
		c.Error(errmsg.ErrResponseParameter)
	}

	// 数据验证
	vali = validation.Validation{}
	vali.Required(reg.Mobile, "mobile").Message("请输入手机号")
	vali.Mobile(reg.Mobile, "mobile").Message("手机号不正确, 由长度为11位的数字组成")
	vali.Required(reg.Password, "password").Message("请输入用户密码")
	vali.Required(reg.Vcode, "vcode").Message("请输入手机验证码")
	if vali.HasErrors() {
		logs.Info("reset password error:", vali.Errors[0])
		c.Error(vali.Errors[0])
		return
	}

	// base64解码
	passDecode, err = base64.StdEncoding.DecodeString(reg.Password)
	if err != nil {
		logs.Error("reset password base64 decode error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	// rsa解密
	pwd, err = tools.Decrypt(passDecode)
	if err != nil {
		logs.Error("reset password password decode error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	// 验证密码
	reg.Password = string(pwd)
	vali.MaxSize(reg.Password, 18, "password").Message("密码由6到18位字符组成")
	vali.MinSize(reg.Password, 6, "password").Message("密码由6到18位字符组成")
	if vali.HasErrors() {
		logs.Info("reset password validate data error:", vali.Errors[0])
		c.Error(vali.Errors[0])
		return
	}

	// 验证短信验证码
	if err = sms.ValidateCode(reg.Mobile, reg.Vcode); err != nil {
		logs.Info("reset password validate sms date error:", err)
		c.Error(err)
		return
	}

	// 判断用户是否已存在
	if !models.IsExistsUser(reg.Mobile) {
		err := errors.New("用户不存在")
		logs.Info("reset password error:", err)
		c.Error(err)
		return
	}

	if err = models.ResetUserPassword(reg.Mobile, reg.Password); err != nil {
		logs.Info("reset password error:", err)
		c.Error(errmsg.ErrResponseSystem)
		return
	}

	// 让在线的用户下线

	c.Success(nil)
}

// @Title sms
// @Description 发送手机验证码
// @router /sms/:mobile [get]
func (c *DefaultController) Sms() {
	mobile, err := c.GetInt64(":mobile")
	if err != nil {
		logs.Info("sms error:", err)
		c.Error(errmsg.ErrResponseParameter)
		return
	}

	valid := validation.Validation{}
	valid.Required(mobile, "mobile").Message("请输入手机号码")
	valid.Mobile(mobile, "mobile").Message("手机号码不正确")
	if valid.HasErrors() {
		c.Error(valid.Errors[0])
		return
	}

	code, err := sms.SetCode(mobile)
	if err != nil {
		logs.Info("sms error:", err)
		c.Error(errmsg.ErrResponseSystem)
	}

	c.Success(&struct {
		Mobile int64
		Code   string
	}{Mobile: mobile, Code: code})
}
